Skip to content

Initial implementation of supervisor#1385

Draft
kuqin12 wants to merge 47 commits intoOpenDevicePartnership:feature/supvfrom
kuqin12:supv_init
Draft

Initial implementation of supervisor#1385
kuqin12 wants to merge 47 commits intoOpenDevicePartnership:feature/supvfrom
kuqin12:supv_init

Conversation

@kuqin12
Copy link
Copy Markdown
Contributor

@kuqin12 kuqin12 commented Mar 11, 2026

Description

This is the initial implementation of MM supervisor and user core in Rust.

  • Impacts functionality?
  • Impacts security?
  • Breaking change?
  • Includes tests?
  • Includes documentation?

How This Was Tested

This was tested on QEMU Q35 platform and booted to OS desktop as well as passed supervisor test app.

Integration Instructions

The integration guide is listed in: https://github.com/kuqin12/mu_feature_mm_supv/blob/personal/kuqin/supv_init/SeaPkg/Docs/PlatformIntegration/PlatformIntegrationSteps.md#integraion-guide-for-rust-based-supervisor. Because it provides the implementation of MM supervisor init module.

@patina-automation
Copy link
Copy Markdown
Contributor

⌛ QEMU Validation Pending

QEMU validation is pending on successful CI completion.

Note: Any previous results are available in this comment's edit history.

This comment was automatically generated by the Patina QEMU PR Validation workflow.

@github-actions github-actions bot added the impact:security Has a security impact label Mar 11, 2026
@kuqin12 kuqin12 marked this pull request as draft March 11, 2026 00:33
@kuqin12 kuqin12 changed the base branch from main to feature/supv March 11, 2026 01:15
///
/// Returns `None` if the slice is too small or misaligned.
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() < Self::SIZE {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe you can skip this indexing check by doing:

Self::read_from_bytes(&bytes.get(..Self::SIZE)?).ok()

<And in the other places you do similar, but I won't comment on them all>

// GUID for gMmSupervisorRequestHandlerGuid
// { 0x8c633b23, 0x1260, 0x4ea6, { 0x83, 0xf, 0x7d, 0xdc, 0x97, 0x38, 0x21, 0x11 } }
/// GUID for the MM Supervisor Request Handler protocol.
pub const MM_SUPERVISOR_REQUEST_HANDLER_GUID: Guid = Guid::from_fields(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe @makubacki can comment, but I believe we have an intent to use our own types, such as patina::BinaryGuid

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. Converting existing code is tracked in #1105. But for new code, we should use it. BinaryGuid is also more ergonomic to work with.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, will update to use BinaryGuid.

// Unblock Memory Params
// ============================================================================

use r_efi::efi;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be at the top of the file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will move.

// Unblock Memory Params
// ============================================================================

use r_efi::efi;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will move.

//! Shared type definitions for MM supervisor and user cores.
//!
//! This crate provides the communication structures and enumerations that define
//! the ABI between the supervisor (ring 0) and user (ring 3) MM modules.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the folder name, it should be common to supv only

@@ -0,0 +1,335 @@
//! Shared MM Pool Allocator
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also only common to supv and user. Unless DXE environment will provide a common layer.

Copy link
Copy Markdown
Contributor

@Javagedes Javagedes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very concerned about the number of global statics in your implementation. I understand it may actually be necessary to be able to perform our SEA validation on the supervisor.

We need to consolidate the statics if possible. If we cannot (due to SEA validation requirements), then we need to make trait abstractions around each of the different statics so that at runtime they all link up, but for testing you can use mockall to mock the different statics. e.g. something like:

static MY_STATIC: SomeStatic = SomeStatic::new();

trait MyTrait {
    fn interface_fn1();
    fn interface_fn2();
}

impl MyTrait for SomeStatic {
    fn interface_fn1() { MY_STATIC.interface_fn1() }
    fn interface_fn2() { MY_STATIC.interface_fn2() }
}

This will allow us to use mockall with the trait to do proper mocking.

/// Implementors provide the actual page allocation mechanism. The supervisor
/// implements this with direct SMRAM bitmap tracking; the user core implements
/// this by issuing syscalls to the supervisor.
pub trait PageAllocatorBackend: Send + Sync {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think this should just be called PageAllocator.

I also don't think you need this is_initialized function. Just let allocate_pages / free_pages return an PageAllocError with maybe a enum variation of NotReady / NotInitialized / etc.

fn is_initialized(&self) -> bool;
}

// ============================================================================
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should get rid of all these AI-esque header block comment things.

@@ -0,0 +1,335 @@
//! Shared MM Pool Allocator
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It really feels like we need to pull out some of the re-usable bits from the patina-dxe-core allocation functionality. I understand not all of that. But as much as possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patian-dxe-core allocation may be useful. But the page allocator for DXE is too GCD centric, which is not a thing in MM. I thought about bringing in GCD, but gave up due to complicated logic and excessive TPL usage.

I briefly looked at the pool allocator from dxe environment. Admittedly, I was scared off by its boot services named statics... I probably need to revisit it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fair. The GCD is very complex, especially if you don't need it.

You could still possibly use some fundamentals like the RBT / BST.

There are also some allocator crates you could use depending on your needs. Just hoping you don't need to completely re-invent the wheel :).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I understand :) The original thought is that we will need to have something to get other functionalities going. I will create an issue on this topic so that we do not lose it.

///
/// Protected by `lock`. The raw pointer is `!Send` but the outer struct
/// provides `Send + Sync` via the lock.
head: Mutex<*mut PoolBlockHeader>,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a great answer here as I'm just doing a skim / pass through this code, but I really think we need a better abstraction around the head here and all of the pointer work you are doing. Not necessarily for this PR but as a task.

@@ -0,0 +1,92 @@
//! Protocol/Handle Database
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we do not want to carry two implementations of the protocol db. We need to abstract or allow configuration enough that the existing protocol db implementation meets your needs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:) that's what I thought as well. then the tpl based lock got in the way and I took the shorter route. Like the allocator comment, we will do that once this stabilizes.

@@ -0,0 +1,378 @@
//! MM Driver Dispatcher
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not implement a whole new dispatcher. We should abstract and allow configurations enough that we can re-use the existing implementation.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the newer crate layout as mentioned earlier.

@@ -0,0 +1,397 @@
//! SMRAM Save State Architecture Definitions
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see a service here. Are you sure this is the right location?

@@ -0,0 +1,135 @@
//! Arch-specific timer functionality
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This already exists does it not? I'm confused.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does, but it was carried inside the dxe specific module. I am trying to get this into a common place. Any suggestions on where that should be? Probably not a component?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will create a separate PR for this for better readability.

makubacki and others added 6 commits March 13, 2026 16:33
…cePartnership#1400)

## Description

patina_mtrr 1.1.5 changed the `Mtrr` trait's `get_memory_ranges()`
return type from `Vec<MtrrMemoryRange>` to
`impl IntoIterator<Item = MtrrMemoryRange>`.

The mockall `mock!` block still uses the concrete Vec type, triggering
the `refining_impl_trait_internal` lint. This commit adds an allow
attribute to the `get_memory_ranges()` method in the mock to suppress
the lint.

- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

- `cargo make all`

## Integration Instructions

- N/A

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
…penDevicePartnership#1402)

## Description

Closes OpenDevicePartnership#583 
Closes OpenDevicePartnership#1396

Adds safety comments to the remaining unsafe blocks in patina_dxe_core
and enables the clippy lint for missing safety docs.

This allows future contributions to have the lint enforced.

- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [x] Includes documentation?

## How This Was Tested

- `cargo make all` with the `undocumented_safety_blocks` clippy lint
enabled in `patina_dxe_core`

## Integration Instructions

- N/A - Safety comments that have no functional impact

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
This function wraps `efi::Guid::from_bytes()` which is const. It is
made const as well.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Add Ord and PartialOrd derives to BinaryGuid, enabling its use as a
BTreeMap key.

Adds a test to verify BinaryGuid's derived ordering matches Guid<'a>'s
byte-order comparison for a set of GUID pairs.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
This change adds a few standard GUID definitions. This is to pave way
for later usage in rust supervisor.
Converts all GUID constants, trait associated types, struct fields,
and other uses to Patina GUID types across the codebase.

Key changes:

- GUID constants mostly use `BinaryGuid::from_string()` since strings
  are more readable than fields. In some cases, a field may have been
  a simple numbering sequence like "123456...", in which case it may
  have been left as `from_fields`.
- Changed `ProtocolInterface::PROTOCOL_GUID` changed to use
  `BinaryGuid`, eliminating duplicated GUID values in implementations.
- Updated `FromHob::HOB_GUID` and `HobParser`s `BTreeMap` key to
  `BinaryGuid`.
- Updated `#[repr(C)]` struct fields (GuidHob, FV/FFS headers,
  MM communicate header) to use `BinaryGuid` since it provides
  binary-compatible GUID storage.
- Updated the `FromHob` proc macro to use `BinaryGuid::from_string()`.
- Updated a lot of code to use Patina GUID types instead of the r-efi
  GUID type.

There were a few places, particularly in UEFI Spec FFI interfaces,
where the `efi::Guid` type is still used. This is intentional to
potentially simplify the r-efi 6.0.0 integration. In code that
interacts with those interfaces, `From` and `Into` functions are used
to simply convert between `BinaryGuid` and `efi::Guid`. Some code
that exclusively interacts with those interfaces, might also use
`efi::Guid` for local GUID definitions instead of Patina GUID types.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
@kuqin12 kuqin12 force-pushed the supv_init branch 2 times, most recently from 8a5c38f to c0baea8 Compare March 16, 2026 21:52
cfernald and others added 4 commits March 16, 2026 14:57
Patina-paging 11.0.2 introduces support for reading/editing existing 5-level
page tables on AArch64. This is required for EDK2 20511 based system that
have FEAT_LPA2 support. To use this change, this commit switches to use
the new `open_active` interface for both AArch64 and x64, which also simplifies
the consumer by handling level detection in the paging library.
writer.rs tests import `crate::reader::AdvancedLogReader`, but
the reader module is conditionally compiled behind
`#[cfg(any(doc, feature = "reader"))]`.

This works when default features are enabled since the "component"
default feature transitively enables "reader".

This change gates `tests` on `#[cfg(all(test, feature = "reader"))]`
so it compiles cleanly when default features are disabled.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Without `--no-default-features` testing, feature-gate regressions go
undetected. Code that accidentally uses a gated module or dependency
outside its `cfg` fence compiles fine under default features but
breaks for consumers that disable defaults.

Since workspace crates like `patina_ffs_extractors` gate optional
compression backends (brotli, crc32, lzma) behind features, and
`patina/patina_internal_collections` gates alloc-dependent code
behind an "alloc" default, verifying the `--no-default-features` build
is useful to catch accidental dependencies on gated code.

Add a higher level `check-no-default-features` task with two parallel
subtasks:

  - `check-no-default-features-code`:
    - `cargo check --no-default-features`
  - `check-no-default-features-tests`:
    - `cargo test --no-run --no-default-features`

Run the task in `cargo make all`.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
## Description

Current patina_stacktrace is pulling in alloc from source code. However,
as basic functionality as the crate provides, the dependency is
improperly included.

This change removes the dependency.

Resolves OpenDevicePartnership#1410

- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

The change is not a functional change and was tested with local build.

## Integration Instructions

N/A
#![cfg(target_arch = "x86_64")]
#![feature(coverage_attribute)]

#![allow(incomplete_features)]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the generic_const_exprs so that the statics will be materialized based on the number of CPUs.

///
/// On the first call (initialization phase), this function returns after init is complete.
/// On subsequent calls, BSP enters the request loop and APs enter the holding pen (neither returns).
pub fn entry_point(&'static self, cpu_index: usize, hob_list: *const c_void) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. This is a fully loaded monolithic flow. Will need to break up based on functionality here.

.ok_or(PolicyInitError::NullHobList)?
};

let mut supv_comm_buffer = 0 as u64;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you have better suggestions here? It is meant to collect the values and should be validated once they are all collected. The validation may not be there yet, but that is in the plan.

}

// Store communication buffer configuration.
COMM_BUFFER_CONFIG.call_once(|| CommBufferConfig {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a one-time initialization by taking the prepared buffer from HOB value. Then following MMIs will consume them rather than always going through the preparation. So in that sense I do want to cache these values, and once only. Any suggestion on how to avoid statics here?


/// A single AP's mailbox for communication with the BSP.
#[repr(C, align(64))] // Cache-line aligned to avoid false sharing
pub struct ApMailbox {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C side has much more complicated data structure to host these functionalities. But I cut the functionalities some and only kept the atomic part. But I agree, this should not be structured to be C like layout.

// GUID for gEfiDxeMmReadyToLockProtocolGuid
// { 0x60ff8964, 0xe906, 0x41d0, { 0xaf, 0xed, 0xf2, 0x41, 0xe9, 0x74, 0xe0, 0x8e } }
/// GUID for the DXE MM Ready To Lock protocol.
pub const EFI_DXE_MM_READY_TO_LOCK_PROTOCOL_GUID: efi::Guid = efi::Guid::from_fields(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

old style

/// GUID for depex data HOBs paired with driver `MemoryAllocationModule` HOBs.
///
/// `gMmSupervisorDepexHobGuid`
pub const MM_SUPERVISOR_DEPEX_HOB_GUID: efi::Guid = efi::Guid::from_fields(
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Old style

}

// SAFETY: MmUserCore is designed to be shared across threads with proper synchronization.
unsafe impl Send for MmUserCore {}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was inherited from supervisor module. Will remove.

@@ -0,0 +1,92 @@
//! Protocol/Handle Database
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:) that's what I thought as well. then the tpl based lock got in the way and I took the shorter route. Like the allocator comment, we will do that once this stabilizes.

@@ -0,0 +1,135 @@
//! Arch-specific timer functionality
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will create a separate PR for this for better readability.

makubacki and others added 4 commits March 17, 2026 13:56
Update the status to indicate that the repository is no longer in a
"beta" stage, but also add a note about the expected stability of the
main branch and the need to verify the readiness of new components.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Clarifies the expectations for contributions that are AI-assisted
to Patina.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Add some more detail to clarify common misunderstandings about Patina.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
)

## Description

This change guards the usage of allocators behind "alloc" to a few
remaining instances in Patina SDK. So that the crate can provide more
fundamental functionalities without dependencies on allocator.

In addition, it removes the `extern crate alloc;` within the crate and
only declare it in the `lib.rs`, which serves as a central feature
controller that governs the entirety of the crate.

Resolves OpenDevicePartnership#1403

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

This was tested by building a binary without global allocator and booted
to UEFI shell on Q35.

## Integration Instructions

Nothing in addition to building the binary with `--features alloc` if a
binary needs allocator functionality.
makubacki and others added 29 commits March 24, 2026 14:31
…penDevicePartnership#1426)

## Description

Closes OpenDevicePartnership#750

Reduces the number of generic type parameters in performance component
functions by dropping the `BB`/`B` and `RR`/`R` indirection pattern.

That pattern used a wrapper type (`BB: AsRef<B>`) alongside its
underlying trait (`B: BootServices`). The `AsRef` indirection is not
needed since `StandardBootServices` and `MockBootServices` both
implement `BootServices + Clone`.

Generic reductions:

- `_entry_point()` from 6 generics (BB, B, RR, R, P, F) to 4 (B, R, P,
F)
- `report_fbpt_record_buffer()` from 5 generics (BB, B, RR, R, F) to 3
(B, R, F)
- `fetch_and_add_mm_performance_records()` from 3 generics (BB, B, F) to
2 (B, F)
- `MmPerformanceEventContext()` from 3 generics (BB, B, F) to 2 (B, F)

Also:

- Replaces `.as_ref().method()` calls with `direct .method()` calls
- Replaces `BB::clone(&x)` with `x.clone()`
- Removes `Rc` wrapping from performance tests

---

- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

- `cargo make all`
- Q35 boot with performance component enabled

## Integration Instructions

- N/A

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Removes the `communicator` pointer from the `ProtocolNotifyContext`
struct and referencing code. This pointer has not been used since a
refactor and is only used for a debug print.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Replaces `Box<dyn MmExecutor>` with a generic type parameter
(`E: MmExecutor + 'static`) that defaults to `RealMmExecutor`. This
keeps the expected default executor for non-test scenarios while
allowing test code to specify other executor types without needing
to box them.

Generic methods (e.g. `with_executor()` and `set_test_comm_buffers()`)
are split into a separate `impl<E>` block since `#[component]` applies
to the default-type impl only. `Debug` and `MmCommunication` impls are
similarly updated to be generic over `E`.

Unit and integration tests now use concrete executor types directly
instead of boxing them.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
…icePartnership#1421)

## Description

Add a `DxeDispatch` service trait in the SDK and a `CoreDxeDispatch`
implementation in patina_dxe_core that delegates to the PI dispatcher.
The service is registered alongside other core services (MemoryManager,
PerfTimer, etc.) and consumed via dependency injection by components
that need to trigger driver dispatch passes.

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

- Built SBSA DXE core binary with `BootDispatcher` + `SimpleBootManager`
consuming the service via DI
- Booted Windows ARM64 under QEMU SBSA-ref with Patina BDS handling the
full boot flow
- Connect-dispatch interleaving discovered AHCI device, expanded partial
device path, loaded Windows bootloader, ExitBootServices completed
- 106 on-system unit tests passed (0 fails)

## Integration Instructions

The `DxeDispatch` service is registered automatically by the DXE core.
Components consume it via dependency injection:

```rust
fn entry_point(self, dxe_dispatch: Service<dyn DxeDispatch>) -> Result<()> {
    dxe_dispatch.dispatch()?;
    Ok(())
}
```
## Description

Patina internal CPU hosts the interrupt manager and other fundamental
functionalities, which should not work on top of the allocator.

Admittedly, the current crate can support more advanced components that
works on top of exception forwarding, but this should not be treated as
a required dependency.

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

This was tested on QEMU Q35 and booted to UEFI shell.

## Integration Instructions

N/A
…1438)

## Description

The previous
[PR](OpenDevicePartnership#1423) merged
with intermittent testing stability: when the tests are run
concurrently, some tests could fail based on timing. i.e.:

https://github.com/OpenDevicePartnership/patina/actions/runs/23577664570/job/68653514272#step:5:1395

The idea is to put a lock on the test and extend the test to register
and unregister within each individual test.

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [x] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

This was tested locally and on the pipeline to not trip on the same
error.

## Integration Instructions

N/A
The HII string lookup in `load_resource_section` calculated the string
data offset as `name_offset + 1`, but `DirectoryString` has a
2-byte length field (followed by the string data), so the correct
offset is `name_offset + sizeof(DirectoryString)`.

"Resource Directory String" is defined here in the PE/COFF spec:

https://learn.microsoft.com/windows/win32/debug/pe-format#resource-directory-string

The comparison constant used was `[0x00, 0x48, 0x00, 0x49, 0x00, 0x49]`
which matched the shifted byte sequence from the wrong offset instead
of the correct UTF-16LE bytes for "HII" which is:
`[0x48, 0x00, 0x49, 0x00, 0x49, 0x00]`.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Today, the code in `load_resource_section` iterates the number of
named entry times but doesn't actually update the `directory_entry`
to the offset for the current iteration. This change makes that
adjustment.

This worked before because images with HII resource sections either
had a sinlge section or the HII section was the first section.

I couldn't find any existing images that have more than one resource
directory entry, so I had to create a simple section with two entries
in the unit test.

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Since `resource_directory_string.length` is a `u16`, a `.length`
value of > 32767 could cause an overflow when multiplied by 2
since the multiplication done before the cast to `usize`.

This change updates the code to perform the multiplication after the
cast to `usize` which is the type the result is assigned to
(the type of `name_end_offset`).

Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com>
Per RFC 25, this patch adds config.toml enforcement
of the Patina config version.

config.toml is updated to reflect the various settings Patina wants
to use. Each is documented on why.

build.rs verifies the patina config version is the correct one and
will fail the build if not.

Docs are updated.

Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
Introduce a `Filter` enum with `Include` and `Exclude` variants rather
than a generic string that is only an inclusion filter.

Exclude filters take priority over include filters. If no include
filters are specified, all non-excluded tests run. The match arms in
`should_run` are exhaustive to ensure new variants cause a compile break.
…p#1377)

The patina_test framework was originally developed inside the SDK crate
to keep `patina_macro` as only a dependency for the `patina` crate. As
we have evolved, other patina related crates have taken a dependency on
`patina_macro`, which means the patina_test framework can be it's own
crate.

This has one large benefit: It simplfies feature logic related to
actually enable or disable the tests. There is now a single feature flag
that is off by default (`test-runner`), and this is how test writers will
consume the crate. When a platform wants to register a test runner with
the Core, it will enable the `test-runner` feature flag, which does two
things: (1) Make the `TestRunner` component public and (2) enable a
feature flag in `patina_macro` to actually register all found patina
tests globally.

The second, smaller benefit, is that we are moving some of the non-sdk
logic out of our SDK crate, and this framework makes sense as a
standalone crate.
This commit updates the `Recorder` service to output test results as
both a human readable format and as a json blob so that it can be
more easily parsed by tooling.
Signed-off-by: Patina Automation Bot <patina@microsoft.com>
## Description

Cleans up and clarifies some elements of existing docs, adds a new
section for rules of thumb for synchronization within Patina.

- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [x] Includes documentation?

## How This Was Tested

Passes md lint.

## Integration Instructions

N/A - documentation.
…nership#1444)

synced local file(s) with
[OpenDevicePartnership/patina-devops](https://github.com/OpenDevicePartnership/patina-devops).

🤖: View the [Repo File Sync Configuration
File](https://github.com/OpenDevicePartnership/patina-devops/blob/main/.sync/Files.yml)
to see how files are synced.



---

This PR was created automatically by the
[repo-file-sync-action](https://github.com/BetaHuhn/repo-file-sync-action)
workflow run
[#23773809455](https://github.com/OpenDevicePartnership/patina-devops/actions/runs/23773809455)

Signed-off-by: Patina Automation Bot <patina@microsoft.com>
Co-authored-by: patina-automation[bot] <196234736+patina-automation[bot]@users.noreply.github.com>
…evicePartnership#1430)

## Description

Allows platforms to provide hardware log level filters for specific log
targets, allowing fine-tuning of the serial port logs. For example,
allows configuring certain info / warn level records to print to serial
when the platform-wide `hw_print_level` is set to error-only.

Implements this by adding a new `hw_filter_override:
Option<log::LevelFilter>` field to the `target_filters` passed to
`AdvancedLogger::new` (which are now a new struct instead of a tuple).
If present, that filter is used for determining whether to print
messages matching the given target prefix to the serial port, instead of
the platform-wide mask from the log header.

Resolves OpenDevicePartnership#1429 

- [x] Impacts functionality?
- [ ] Impacts security?
- [x] Breaking change?
- [x] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

Verified HW filtering behavior works as expected on a physical platform
(ARM).

## Integration Instructions

Change `target_filters` parameter of `AdvancedLogger::new()` to use a
list of the new `TargetFilter` struct instead of the previous tuple of
`(&'a str, log::LevelFilter)`.

For example:
```rust
static LOGGER: AdvancedLogger<UartNull> = AdvancedLogger::new(
   Format::Standard, // How logs are formatted
   &[("allocations", LevelFilter::Off)], // set custom log levels per module
   log::LevelFilter::Info, // Default log level
   UartNull { }, // Serial writer instance
);
```
becomes
```rust
static LOGGER: AdvancedLogger<UartNull> = AdvancedLogger::new(
   Format::Standard, // How logs are formatted
   &[TargetFilter { target: "allocations", log_level: LevelFilter::Off, hw_filter_override: None }], // set custom log levels per module
   log::LevelFilter::Info, // Default log level
   UartNull { }, // Serial writer instance
);
```

---------

Co-authored-by: Thomas Hinds <hindsthomas@microsoft.com>
…mption (OpenDevicePartnership#1413)

## Description

Current patina_mm carries some definitions that can be shared by
external users (mm communication header, buffer status, etc).

This change moves those files to a sub-module that does not require
alloc.

It also separates the supervisor related definitions into its own file.

Resolves OpenDevicePartnership#1437.

- [x] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

This was tested with local builds and booted to UEFI shell.

## Integration Instructions

N/A
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

impact:security Has a security impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants